package client

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"

	"gitee.com/zh-jn/harmonica-previewer-online/api"
	"gitee.com/zh-jn/harmonica-previewer-online/previewer/harmonica/v1/manager"
)

type ClientConfig struct {
	Addr string
	Port int
}

type ManagerClient struct {
	cfg ClientConfig
	c   *http.Client
}

func NewManagerClient(cfg ClientConfig) *ManagerClient {
	return &ManagerClient{
		cfg: cfg,
		c:   &http.Client{},
	}
}

func (c *ManagerClient) AllocatePreviewer(sessionId string) (previewerD manager.PreviewerDescriptor, e error) {
	var rsp *http.Response
	req := manager.AllocatePreviewerReq{
		SessionId: sessionId,
	}
	reqbuf, err := json.Marshal(req)
	if err != nil {
		e = err
		return
	}
	rsp, e = c.c.Post(fmt.Sprintf("http://%v:%v/allocate_previewer", c.cfg.Addr, c.cfg.Port), "", bytes.NewReader(reqbuf))
	if e != nil {
		return
	}

	rspbody, err := ioutil.ReadAll(rsp.Body)
	if err != nil {
		e = err
		return
	}

	if e = api.ReadRsp(rspbody, &previewerD); e != nil {
		return
	}

	return
}

func (c *ManagerClient) CheckBinding(sessionId, previewerId string) (e error) {
	var rsp *http.Response
	req := manager.CheckBindingReq{
		AllocatePreviewerReq: manager.AllocatePreviewerReq{
			SessionId: sessionId,
		},
		PreviewerId: previewerId,
	}
	reqbuf, err := json.Marshal(req)
	if err != nil {
		e = err
		return
	}
	rsp, e = c.c.Post(fmt.Sprintf("http://%v:%v/check_binding", c.cfg.Addr, c.cfg.Port), "", bytes.NewReader(reqbuf))
	if e != nil {
		return
	}
	rspBody, err := ioutil.ReadAll(rsp.Body)
	if err != nil {
		e = err
		return
	}

	if e = api.ReadRsp(rspBody, nil); e != nil {
		return
	}

	return
}

func (c *ManagerClient) ReleasePreviewer(sessionId, previewerId string) (e error) {
	var rsp *http.Response
	req := manager.ReleasePreviewerReq{
		AllocatePreviewerReq: manager.AllocatePreviewerReq{
			SessionId: sessionId,
		},
		PreviewerId: previewerId,
	}
	reqbuf, err := json.Marshal(req)
	if err != nil {
		e = err
		return
	}
	rsp, e = c.c.Post(fmt.Sprintf("http://%v:%v/release_previewer", c.cfg.Addr, c.cfg.Port), "", bytes.NewReader(reqbuf))
	if e != nil {
		return
	}
	rspBody, err := ioutil.ReadAll(rsp.Body)
	if err != nil {
		e = err
		return
	}

	if e = api.ReadRsp(rspBody, nil); e != nil {
		return
	}

	return
}
